#include "tcp.h"
#include "tcp_timer.h"
#include "tcp_sock.h"

#include <stdio.h>
#include <unistd.h>

static struct list_head timer_list = {&timer_list, &timer_list};
static pthread_mutex_t timer_list_lock = PTHREAD_MUTEX_INITIALIZER;

// scan the timer_list, find the tcp sock which stays for at 2*MSL, release it
#include "log.h"
// scan timer list need LOCK 互斥

//const char *tcp_state_c_str[] = { "OPEN", "DISORDER", "RECOVERY", "LOSS" };

void tcp_scan_timer_list()
{

	// log(DEBUG, "lock timer scan");
	struct tcp_timer *timer, *tmp;

	// Iterate through the timer_list to find expired time-wait timers
	if (!(list_empty(&timer_list)))
	{
		list_for_each_entry_safe(timer, tmp, &timer_list, list)
		{
			if (pthread_mutex_lock(&timer_list_lock) == 0)
			{
				// log(DEBUG, "lock pthread succeed");
			}
			else
			{
				// log(ERROR, "lock pthread failed");
			}
			// Update the timeout: decrement the timer's timeout
			timer->timeout -= TCP_TIMER_SCAN_INTERVAL;
			// log(DEBUG, "updating sock timer, now timeout is %d", timer->timeout);

			if (timer->timeout <= 0)
			{
				// Timer expired
				if (timer->type == 0)
				{ // WAIT type
					struct tcp_sock *tsk = timewait_to_tcp_sock(timer);
					log(INFO, "TIME-WAIT timer expired for TCP sock");
					// Delete tsk: unhash, free, and delete responding timer from timer_list
					// log(DEBUG, "tsk state is %s", tcp_state_to_str(tsk->state));
					list_delete_entry(&timer->list);
					tcp_set_state(tsk, TCP_CLOSED);
					tcp_process(tsk, NULL, NULL);
				}

				else if (timer->type == 1)// RETRANS type
								// 现在也需要更新对拥塞控制的支持
				{ 
					if(!timer->enable){
						log(DEBUG,"tcp_scan_timer_list: expired, but retrans timer not enabled, no need to retrans");
						return;
					}

	
					struct tcp_sock *tsk = retranstimer_to_tcp_sock(timer);
					// Congestion control 
					// 超时，强制进入LOSS状态
					if(tsk->c_state==TCP_CONG_OPEN){
						tcp_set_c_state(tsk,TCP_CONG_LOSS);
					}

					if(tsk->c_state==TCP_CONG_DISORDER){
						log(DEBUG,"tcp_scan_timer_list: RTO happens in disorder state");
						tcp_set_c_state(tsk, TCP_CONG_LOSS);
					}
					if(tsk->c_state==TCP_CONG_RECOVERY){
						log(DEBUG,"tcp_scan_timer_list: RTO happens in recovery state");
						tcp_set_c_state(tsk, TCP_CONG_LOSS);
					}


					log(WARNING, "Retransmission timer expired for TCP sock");
					if (tsk->state == TCP_CLOSED || tsk->state == TCP_CLOSING)
					{
						// 已关闭无需重传
						return;
					}
					// 进行重传
					if (timer->retrans_cnt >= 3)
					{ // 达到重传次数上限
						// 强制关闭socket
						log(WARNING, " Reached maximum retransmission count, closing socket");

						if (!tsk)
						{
							log(ERROR, "tcp_sock is NULL, cannot close socket");
							return;
						}
						tcp_send_control_packet(tsk, TCP_RST | TCP_ACK);

						tcp_set_state(tsk, TCP_CLOSED);
						wake_up(tsk->wait_connect);
						wake_up(tsk->wait_accept);
						log(ERROR, "Socket closed due to retransmission timeout");
						return;
					}
					else
					{ // 未达到上限，进行重传，更新重传次数，RTO，超时时间，更新拥塞控制状态
						tcp_retrans_send_buffer(tsk);
						timer->retrans_cnt++;
						// 更新RTO 和 time out
						timer->RTO*=2;
						timer->timeout = timer->RTO;
						//log(WARNING,"tcp_scan_timer_list: now the RTO update to %d",timer->RTO);

						log(INFO,"tcp_congestion_control: TIME OUT, reset congestion parameters");

					
						tsk->ssthresh = tsk->cwnd/2;
						tsk->cwnd=TCP_MSS;
						tsk->dupACKcount=0;
			

						// 重传完成，改变状态
						tcp_set_c_state(tsk, TCP_CONG_OPEN);
					}
				}

				else if (timer->type == 2)// PERSIST type

				{ 
					/*
						tcp_scan_timer_list中增加对Persist Timer超时的处理。
						如果TCP没有关闭，且发送窗口snd_wnd小于TCP_MSS，
						则发送一个Probe报文、重置时间，否则关闭该定时器。
					*/

					struct tcp_sock *tsk = persisttimer_to_tcp_sock(timer);

					log(DEBUG, "PERSIST timer expired for TCP sock");
					// Check if the sending window is less than TCP_MSS
					if (tsk->state != TCP_CLOSED && tsk->snd_wnd < TCP_MSS)
					{
						// Send a probe packet to check if the connection is still alive
						log(INFO, "Sending probe packet to check if connection is alive");
						tcp_send_probe_packet(tsk);
						// Reset the timeout for the persist timer
						timer->timeout = TCP_RETRANS_INTERVAL_INITIAL;
					}
					else
					{
						// If the sending window is not less than TCP_MSS, disable the persist timer
						tcp_unset_persist_timer(tsk);
					}
				}
			}

			if (pthread_mutex_unlock(&timer_list_lock) != 0)
			{
				log(ERROR, "Failed to unlock timer_list_lock");
			}
		}
	}
}

// set the timewait timer of a tcp sock, by adding the timer into timer_list
void tcp_set_timewait_timer(struct tcp_sock *tsk)
{
	// check if tsk at WAIT state
	if (tsk->state == TCP_TIME_WAIT)
	{
		// initialize tsk waiter
		// enabling it
		tsk->timewait.enable = 1;
		// set type to wait (0)
		tsk->timewait.type = 0;
		// set timeout to 2*MSL
		tsk->timewait.timeout = TCP_TIMEWAIT_TIMEOUT;
	}

	// add up to list:在TCP进入TIME_WAIT状态时，设置定时器并将其加入timer_list尾部
	list_add_tail(&tsk->timewait.list, &timer_list);
}

// scan the timer_list periodically by calling tcp_scan_timer_list
void *tcp_timer_thread(void *arg)
{
	init_list_head(&timer_list);
	while (1)
	{
		usleep(TCP_TIMER_SCAN_INTERVAL);
		tcp_scan_timer_list();
	}

	return NULL;
}

void tcp_set_persist_timer(struct tcp_sock *tsk)
{
	if (tsk->persist_timer.enable)
	{
		log(DEBUG, "Persist timer already enabled, no need to set again.");
		return;
	}

	// Initialize the persist timer
	tsk->persist_timer.enable = 1;
	tsk->persist_timer.type = 2;							   // Set type to persist (2)
	tsk->persist_timer.timeout = TCP_RETRANS_INTERVAL_INITIAL; // Set initial timeout

	tsk->ref_cnt += 1;									  // Increase reference count for the timer
	list_add_tail(&tsk->persist_timer.list, &timer_list); // Add to the timer list
}

void tcp_unset_persist_timer(struct tcp_sock *tsk)
{
	if (!tsk->persist_timer.enable)
	{
		log(DEBUG, "Persist timer already disabled, no need to unset.");
		return;
	}

	tsk->persist_timer.enable = 0; // Disable the persist timer
	// free_tcp_sock will decrease ref_cnt, and if it reaches 0, free the tcp_sock
	free_tcp_sock(tsk);

	list_delete_entry(&tsk->persist_timer.list); // Remove from the timer list
}

// 设置重传计时器 set retrans timer
void tcp_set_retrans_timer(struct tcp_sock *tsk)
{
	if (tsk->retrans_timer.enable==1)
	{
		log(DEBUG, "Retransmission timer already enabled, set time-out to now RTO");
		tsk->retrans_timer.timeout=tsk->retrans_timer.RTO;
		return;
	}

	// Initialize the retransmission timer
	tsk->retrans_timer.enable = 1;
	tsk->retrans_timer.type = 1;							   // Set type to retrans (1)
	
	tsk->retrans_timer.RTO =TCP_RETRANS_INTERVAL_INITIAL;
	tsk->retrans_timer.timeout=tsk->retrans_timer.RTO;
	
	tsk->retrans_timer.retrans_cnt=0;

	tsk->ref_cnt += 1;									  // Increase reference count for the timer
	list_add_tail(&tsk->retrans_timer.list, &timer_list); // Add to the timer list
	log(DEBUG,"tcp_set_retrans_timer: set the retrans timer and eable it");
}

void tcp_unset_retrans_timer(struct tcp_sock *tsk)
{
	if (tsk->retrans_timer.enable==0)
	{
		log(DEBUG, "Retransmission timer already disabled, no need to unset.");
		return;
	}
	log(INFO, "Disabling retransmission timer for TCP sock");

	tsk->retrans_timer.enable = 0; // Disable the retransmission timer
	free_tcp_sock(tsk);			   // Decrease reference count and free if necessary

	list_delete_entry(&tsk->retrans_timer.list); // Remove from the timer list
}

void tcp_update_retrans_timer(struct tcp_sock *tsk)
{

	if (!tsk->retrans_timer.enable)
	{
		log(DEBUG, "tcp_update_retrans_timer: Retransmission timer not enabled, no need to update. ");
		//wake_up(tsk->wait_send);
		return;
	}

	// 如果发送队列为空，删除定时器，唤醒发送数据进程。
	// 这个意思就是重传要睡一下？
	if (list_empty(&tsk->send_buf))
	{
		tsk->retrans_timer.enable=0;
		tsk->retrans_timer.retrans_cnt=0;

		log(DEBUG, "tcp_update_retrans_timer: Send buf is empty, disabling retransmission timer.");

		list_delete_entry(&tsk->retrans_timer.list);
		
		wake_up(tsk->wait_send);	  // Wake up the sending process
	}
	else
	{ // 否则重置计时器，包括timeout和重传次数
		// Reset the retransmission timer timeout and  count
		log(DEBUG, "Updating retransmission timer timeout and count.");
		tsk->retrans_timer.RTO=TCP_RETRANS_INTERVAL_INITIAL;
		tsk->retrans_timer.timeout = tsk->retrans_timer.RTO; // Reset timeout
		tsk->retrans_timer.retrans_cnt = 0;						   // Reset retransmission count to 0
	}
}
